package com.ssy.lingxi.contract.serviceimpl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.contract.api.model.vo.request.ContrPriceQueryRequest;
import com.ssy.lingxi.contract.api.model.vo.request.ContractOrderMaterielRequest;
import com.ssy.lingxi.contract.api.model.vo.request.PurchaseMaterielPriceRequestVO;
import com.ssy.lingxi.contract.api.model.vo.response.PurchaseMaterielPriceVO;
import com.ssy.lingxi.contract.entity.ContractPurchaseMaterielDO;
import com.ssy.lingxi.contract.model.constant.CommonBooleanEnum;
import com.ssy.lingxi.contract.model.constant.ContractOrderChangeTypeEnum;
import com.ssy.lingxi.contract.model.vo.common.request.PurchaseMaterielPageVO;
import com.ssy.lingxi.contract.model.vo.common.response.PurchaseMaterielQueryVO;
import com.ssy.lingxi.contract.model.vo.coordination.request.AssociatedGoodsUpdateVO;
import com.ssy.lingxi.contract.model.vo.manage.request.PurchaseMaterielUpdateVO;
import com.ssy.lingxi.contract.repository.ContractPurchaseMaterielRepository;
import com.ssy.lingxi.contract.service.IContractPurchaseMaterielService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 合同采购物流接口实现
 * @author 伍将
 * @date 2021/2/8
 * @version 2.0.0
 */
@Service
@Slf4j
public class ContractPurchaseMaterielServiceImpl implements IContractPurchaseMaterielService {

    @Resource
    private ContractPurchaseMaterielRepository repository;
//    @Resource
//    private IFeignService feignService;

    /**
     * 分页查询合同采购物料
     * @author 伍将
     * @date 2021/2/8
     * @param user: 当前登录用户
     * @param pageVO: 分页查询请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<PageData<PurchaseMaterielQueryVO>> pageList(UserLoginCacheDTO user, PurchaseMaterielPageVO pageVO) {

        // 组装查询条件
        Specification<ContractPurchaseMaterielDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("contractId").as(Long.class), pageVO.getContractId()));
            if(StringUtils.hasLength(pageVO.getMaterielNo())){
                list.add(criteriaBuilder.equal(root.get("materielNo").as(String.class), pageVO.getMaterielNo()));
            }
            if(StringUtils.hasLength(pageVO.getCode())){
                list.add(criteriaBuilder.like(root.get("materielNo").as(String.class), "%" +pageVO.getCode()+"%"));
            }
            if(StringUtils.hasLength(pageVO.getMaterielName())){
                list.add(criteriaBuilder.like(root.get("materielName").as(String.class), "%" +pageVO.getMaterielName()+"%"));
            }
            if(StringUtils.hasLength(pageVO.getType())){
                list.add(criteriaBuilder.like(root.get("type").as(String.class),"%" + pageVO.getType()+"%"));
            }
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("materielNo").descending());

        Page<ContractPurchaseMaterielDO> result = repository.findAll(spec, page);
        //商品id
//        List<Long> goodsIds = new ArrayList<>();
//        Set<Long> uniqueValues = new HashSet<>();
//        for (ContractPurchaseMaterielDO contractPurchaseMaterielDO : result.getContent()) {
//            Long associatedDataId = contractPurchaseMaterielDO.getAssociatedDataId();
//            if (associatedDataId != null) {
//                if (uniqueValues.add(associatedDataId)) {
//                    goodsIds.add(associatedDataId);
//                }
//            }
//        }
/*暂不显示0806        Map<Long, CommoditySkuStockResponse> commoditySkuStock =  getCommoditySkuStock(user, goodsIds,pageVO.getShopId());
        boolean stockFlag = CollectionUtil.isNotEmpty(commoditySkuStock);*/
        List<PurchaseMaterielQueryVO> resultList = result.getContent().stream().map(o -> {
            PurchaseMaterielQueryVO entity = new PurchaseMaterielQueryVO();
            //by 万宁： 要传递来自商品服务的物料Id
            //entity.setId(o.getId());
            entity.setId(o.getMaterielId());
            entity.setMaterielNo(o.getMaterielNo());
            entity.setMaterielName(o.getMaterielName());
            entity.setType(o.getType());
            entity.setCategory(o.getCategory());
            entity.setBrand(o.getBrand());
            entity.setUnit(o.getUnit());
            entity.setIsHasTax(o.getIsHasTax());
            entity.setIsHasTaxName(CommonBooleanEnum.getMessage(o.getIsHasTax()));
            entity.setTaxRate(o.getTaxRate());
            entity.setType(o.getType());
            entity.setPurchaseCount(o.getPurchaseCount());
            entity.setPrice(o.getPrice());
            entity.setBidCount(o.getBidCount());
            entity.setBidAmount(o.getBidAmount());
            entity.setAssociatedGoods(o.getAssociatedGoods());
            entity.setAssociatedDataId(o.getAssociatedDataId());
/*            entity.setAssociatedMaterielNo(o.getAssociatedMaterielNo());
            entity.setAssociatedMaterielName(o.getAssociatedMaterielName());*/
            entity.setAssociatedType(o.getAssociatedType());
            entity.setAssociatedCategory(o.getAssociatedCategory());
            entity.setAssociatedBrand(o.getAssociatedBrand());
            Double contractFreeCount = o.getContractFreeCount();
            entity.setContractFreeCount((contractFreeCount==null||contractFreeCount<0)?0D:contractFreeCount);
/* 暂不显示0806           if(stockFlag){
                CommoditySkuStockResponse stockResponse = commoditySkuStock.get(o.getAssociatedDataId());
                if(stockResponse!=null) {
                    //供方库存
                    entity.setSupplierInventory(stockResponse.getStock());
                }else{
                    entity.setSupplierInventory(0D);
                }
            }*/
            return entity;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

//    private Map<Long,CommoditySkuStockResponse> getCommoditySkuStock(UserLoginCacheDTO user, List<Long> goodsIds,Long shopId){
//        if(CollectionUtil.isEmpty(goodsIds)){
//            return null;
//        }
//        CommodityPriceRequest request=new CommodityPriceRequest();
//        request.setMemberId(user.getMemberId());
//        request.setMemberRoleId(user.getMemberRoleId());
//        request.setCommoditySkuIdList(goodsIds);
//        request.setCommodityType(1);
//        request.setShopId(shopId);
//        Wrapper<List<CommoditySkuStockResponse>> commoditySkuStock = feignService.getCommoditySkuStock(request);
//        if(commoditySkuStock==null || ResponseCode.SUCCESS.getCode()!=commoditySkuStock.getCode()){
//            throw new BusinessException(ResponseCode.FEIGN_SERVICE_ERROR);
//        }
//        if(CollectionUtil.isNotEmpty(commoditySkuStock.getData())){
//            return commoditySkuStock.getData().stream().collect(Collectors.toMap(CommoditySkuStockResponse::getCommoditySkuId, o->o,(o1, o2)->o2));
//        }
//        return null;
//    }

    /**
     * 保存合同采购物料
     * @author 伍将
     * @date 2021/2/25
     * @param contractId: 合同id
     * @param purchaseMaterielList: 采购物料
     * @return 操作结果
     **/
    @Transactional
    @Override
    public Wrapper<Void> save(Long contractId, List<PurchaseMaterielUpdateVO> purchaseMaterielList) {
        // 查询旧数据
        List<ContractPurchaseMaterielDO> oldList = repository.findByContractId(contractId);


        // 如果存在旧数据，进行匹配删除
        if (oldList.size() > 0) {
            List<ContractPurchaseMaterielDO> delList = oldList.stream().filter(o ->
                    !purchaseMaterielList.stream().map(PurchaseMaterielUpdateVO::getId)
                            .collect(Collectors.toList())
                            .contains(o.getId()))
                    .collect(Collectors.toList());

            // 删除旧数据
            repository.deleteAll(delList);
        }

        // 组装新增/更新数据
        List<ContractPurchaseMaterielDO> addList = purchaseMaterielList.stream().map(o -> {
            ContractPurchaseMaterielDO entity = new ContractPurchaseMaterielDO();
            entity.setId(o.getId());
            entity.setContractId(contractId);
            entity.setMaterielId(o.getMaterielId());
            entity.setMaterielNo(o.getMaterielNo());
            entity.setMaterielName(o.getMaterielName());
            entity.setType(o.getType());
            entity.setCategory(o.getCategory());
            entity.setBrand(o.getBrand());
            entity.setUnit(o.getUnit());
            entity.setIsHasTax(o.getIsHasTax());
            entity.setTaxRate(o.getTaxRate());
            entity.setPrice(o.getPrice());
            entity.setPurchaseCount(o.getPurchaseCount());
            entity.setBidAmount(o.getBidAmount());
            entity.setBidCount(o.getBidCount());
            entity.setContractFreeCount(o.getBidCount());
            entity.setAssociatedDataId(o.getAssociatedDataId());
            entity.setAssociatedGoods(o.getAssociatedGoods());
            entity.setAssociatedType(o.getAssociatedType());
            entity.setAssociatedCategory(o.getAssociatedCategory());
            entity.setAssociatedBrand(o.getAssociatedBrand());
            return entity;
        }).collect(Collectors.toList());
        repository.saveAll(addList);

        return Wrapper.success();
    }

    /**
     * 更新采购物料
     * @author 伍将
     * @date 2021/3/2
     * @param updateVO: 更新请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<Void> update(AssociatedGoodsUpdateVO updateVO) {
        // 检查采购物料是否存在
        ContractPurchaseMaterielDO entity = repository.findById(updateVO.getPurchaseMaterielId()).orElse(null);
        if (null == entity) {
            throw new BusinessException(ResponseCode.CONTRACT_PURCHASE_MATERIEL_NOT_EXIST);
        }

        // 验证采购物料是否所属合同
        if (!updateVO.getContractId().equals(entity.getContractId())) {
            throw new BusinessException(ResponseCode.CONTRACT_PURCHASE_MATERIEL_CONTRACT_ID_ERROR);
        }

        entity.setAssociatedDataId(updateVO.getAssociatedDataId());
        entity.setAssociatedGoods(updateVO.getAssociatedGoods());
        entity.setAssociatedType(updateVO.getAssociatedType());
        entity.setAssociatedCategory(updateVO.getAssociatedCategory());
        entity.setAssociatedBrand(updateVO.getAssociatedBrand());
        repository.saveAndFlush(entity);

        return Wrapper.success();
    }

    /**
     * 校验合同-是否已全部关联商品
     * @author ds
     * @date 2021/5/28
     * @param contractId: 合同id
     * @return 操作结果
     **/
    @Override
    public Boolean checkContractAssociatedGoods(Long contractId) {
        // 检查采购物料是否存在
        boolean result=Boolean.TRUE;
        List<ContractPurchaseMaterielDO> materielDOS = repository.findByContractId(contractId);
        if(CollectionUtil.isEmpty(materielDOS)){
            return Boolean.FALSE;
        }
        for(ContractPurchaseMaterielDO o: materielDOS){
            if(o.getAssociatedDataId()==null||!StringUtils.hasLength(o.getAssociatedGoods())){
                result=Boolean.FALSE;
                break;
            }
        }
        return result;
    }

    /**
     * 根据合同id删除采购物料
     * @author 伍将
     * @date 2021/3/3
     * @param contractId: 合同id
     * @return 操作结果
     **/
    @Override
    public Wrapper<Void> deleteByContractId(Long contractId) {
        repository.deleteByContractId(contractId);

        return Wrapper.success();
    }

    /**
     * 查询采购物料单价
     * @author 伍将
     * @date 2021/3/19
     * @param requestVO: 请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<List<PurchaseMaterielPriceVO>> getPriceList(PurchaseMaterielPriceRequestVO requestVO) {
        if(CollectionUtil.isEmpty(requestVO.getMaterielIdList())&&CollectionUtil.isEmpty(requestVO.getMaterielNoList())){
            throw new BusinessException(ResponseCode.CONTRACT_MATERIEL_ID_OR_NO_IS_REQUIRED);
        }
        List<ContractPurchaseMaterielDO> materielList =null;
        if(CollectionUtil.isNotEmpty(requestVO.getMaterielIdList())) {
            materielList = repository.findByContractIdAndIdIn(requestVO.getContractId(), requestVO.getMaterielIdList());
        }else if(CollectionUtil.isNotEmpty(requestVO.getMaterielNoList())){
            materielList = repository.findByContractIdAndMaterielNoIn(requestVO.getContractId(), requestVO.getMaterielNoList());
        }
        if(materielList==null){
            return Wrapper.success();
        }
        return Wrapper.success(
                materielList.stream().map(o -> {
                    PurchaseMaterielPriceVO entity = new PurchaseMaterielPriceVO();
                    entity.setContractId(o.getContractId());
                    entity.setMaterielId(o.getId());
                    entity.setMaterielNo(o.getMaterielNo());
                    entity.setPrice(o.getPrice());
                    return entity;
                }).collect(Collectors.toList())
        );
    }

    @Transactional
    @Override
    public void updateContractPurchaseMaterielCount(Long contractId, List<ContractOrderMaterielRequest> contractOrderMaterielRequestList, Integer type){
        List<ContractPurchaseMaterielDO> purchaseMaterielDOList = repository.findByContractId(contractId);
        if(CollectionUtil.isEmpty(purchaseMaterielDOList)){
            log.error("updateContractPurchaseMaterielCount 合同物料信息不存在，contractId:{}",contractId);
        }
        //必须传关联商品id，
        purchaseMaterielDOList.forEach(m -> contractOrderMaterielRequestList.forEach(o->{
            if(m.getMaterielId()!=null&&m.getMaterielNo()!=null) {
                if (m.getMaterielId().equals(o.getAssociatedDataId()) && m.getMaterielNo().equals(o.getAssociatedMaterielNo())) {
                    if (ContractOrderChangeTypeEnum.ADD.getCode().equals(type)) {
                        m.setContractFreeCount(NumberUtil.sub(m.getContractFreeCount(), o.getCount()));
                    } else if (ContractOrderChangeTypeEnum.CANCEL.getCode().equals(type)) {
                        m.setContractFreeCount(NumberUtil.add(m.getContractFreeCount(), o.getCount()));
                    }
                }
            }else{
                log.warn("updateContractPurchaseMaterielCount采购物料(商品)id数据错误：{}", JSONUtil.toJsonStr(m));
            }
        }));
        repository.saveAll(purchaseMaterielDOList);
    }

    /**
     * 根据物料编码查询物料合同信息
     * @param request 物料信息
     * @return 物料合同信息
     */
    @Override
    public List<ContractPurchaseMaterielDO> selectGoods(ContrPriceQueryRequest request) {
        List<ContractPurchaseMaterielDO> materielDOList = repository.findByMaterielNo(request.getCode());
        if (CollectionUtils.isEmpty(materielDOList)){
            return new ArrayList<>();
        }
        return materielDOList;
    }

    @Override
    public List<ContractPurchaseMaterielDO> selectGoodsByContractId(Long contractId) {
        return repository.findByContractId(contractId);
    }
}
